test_name "CVE 2013-1652 Poison node cache" do

  tag 'audit:high',        # low risk, high (security) impact
      'audit:integration', # master side only
      'server'

  step "Determine suitability of the test" do
    skip_test( "This test will only run on Puppet 3.x" ) if
      on(master, puppet('--version')).stdout =~ /\A2\./
  end

  with_puppet_running_on( master, {} ) do
    # Ensure agent has a signed cert
    on master, puppet('agent', '-t' )

    certname = on(
      master, puppet('agent', "--configprint certname")).stdout.chomp
    cert_path = on(
      master, puppet('agent', "--configprint hostcert")).stdout.chomp
    key_path = on(
      master, puppet('agent', "--configprint hostprivkey")).stdout.chomp

    curl_base = "curl --tlsv1 -g --cert \"#{cert_path}\" " +
                "--key \"#{key_path}\" -k -H 'Accept: pson'"

    step "Attempt to poison the master's node cache" do
      yamldir = puppet_config(master, 'yamldir', section: 'master')
      exploited = "#{yamldir}/node/you.lose.yaml"
      on master, "rm -rf #{exploited}"
      on master, "rm -rf #{yamldir}/node/*"
      payload2 = "https://#{master}:8140/puppet/v3/node/#{certname}?environment=production" +
                 "&instance=---+%21ruby%2Fobject%3APuppet%3A%3ANode%0A+classes" +
                 "%3A%0A+-+foo%0A+name%3A+you.lose%0A+parameters" +
                 "%3A+%7B%7D%0A+time%3A+2013-02-28+15%3A12%3A30.367008+-08%3A00"

      on master, "#{curl_base} '#{payload2}'"

      fail_test( "Found exploit file #{exploited}" ) if
        on( master, "[ ! -f #{exploited} ]",
           :acceptable_exit_codes => [0,1] ).exit_code == 1
    end
  end
end
